
/**
 * Permits to avoid manual explicit binding.
 * 
 * http://blog.kassens.net/binds-class-mutator
 * 
 * \code
 * var MyClass = new Class(
 * {
 * 	Binds: ['sayHello', 'sayGoodbye'],
 * 	
 * 	initialize: function()
 * 	{
 * 		// now only using this.sayHello and
 * 		// this.sayGoodbye inside the class
 * 	},
 * 	sayHello: function() {  },
 * 	sayGoodbye: function() {  }
 * });
 * \endcode
 */
Class.Mutators.Binds = function(self, methods)
{
	$splat(methods).each(function(method)
	{
      	var fn = self[method];
		self[method] = function() {
			return fn.apply(self, arguments);
		};
	});
};

/**
 * Permits to avoid manual explicit binding of events callbacks.
 */
Class.Mutators.BindsWithEvent = function(self, methods)
{
	$splat(methods).each(function(method) {
		self[method] = self[method].create({bind: self, event: true});
	});
};

/**
 * Adds the event 'outerclick', triggered only when clicked outside of an element.
 * 
 * http://blog.kassens.net/outerclick-event
 * 
 * \code
 * $('dialog').addEvent('outerclick', function() {  });
 * \endcode
 */
(function()
{
	var events;
	var check = function(e)
	{
		var target  = $(e.target);
		var parents = target.getParents();
		
		events.each(function(item)
		{
			var element = item.element;
			if (element != target && !parents.contains(element)) {
				item.fn.call(element, e);
			}
		});
	};
	
	Element.Events.outerclick = {
		onAdd: function(fn)
		{
			if(!events)
			{
				window.addEvent('click', check);
				events = [];
			}
			events.push({element: this, fn: fn});
		},
		
		onRemove: function(fn)
		{
			events = events.filter(function(item) {
				return item.element != this || item.fn != fn;
			}, this);
			
			if (!events.length)
			{
				window.removeEvent('click', check);
				events = null;
			}
		}
	};
})();
